// Copyright 2011 George Cook
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.


#import "BaseTest.h"
#import <GHUnit/GHUnit.h>
#import "InjectivePropertyValueDescription.h"
#import "Injective.h"
#import "InjectiveContextXMLFactory.h"
#import "InjectiveContainer.h"
#import "InjectivePropertyDescription.h"
#import "InjectiveObjectDescription.h"
#import "InjectiveArrayPropertyValueDescription.h"

@interface InjectiveContainerMock : InjectiveContainer
{
}
@end

@implementation InjectiveContainerMock
- (id) getObjectByPropertyDescription:(InjectivePropertyDescription *)propertyDescription
{
	return [propertyDescription.type isEqualToString:@"FunkyProvider" ] ? @"CORRECT" : @"CORRECT2";
}

@end



@interface InjectiveArrayPropertyValueDescriptionTest : BaseTest
{
	InjectiveContextXMLFactory *factory;
	InjectiveContainer *container;
}
@end


@implementation InjectiveArrayPropertyValueDescriptionTest
- (void)setUp
{
	factory = [[InjectiveContextXMLFactory alloc] init];
	container = [[InjectiveContainerMock alloc] init];
}

- (void)tearDown
{
	[factory release], factory = nil;
	[container release], container = nil;
}


- (void)testRealValue
{
	//sanity check on the descriptions
	
	NSArray *descriptions = [factory processXMLFile:@"testArrayValue.xml"];
	GHAssertNotNil(descriptions, @"no descriptions were generated");
	InjectiveObjectDescription *description = [descriptions lastObject];
	GHAssertNotNil(description.propertyDescriptions, @"there were no property descriptions");
	GHAssertTrue(1 == description.propertyDescriptions.count, @"didn't create 1 property, created %d", description.propertyDescriptions.count);
	InjectivePropertyDescription *propertyDescription = [description.propertyDescriptions lastObject];
	GHAssertTrue([propertyDescription.type isEqualToString:@"Array"],@"didn't detect correct type");
	GHAssertTrue([propertyDescription.propertyName isEqualToString:@"arrayValue"],@"didn't detect correct property name");
	InjectiveArrayPropertyValueDescription *arrayDescription = (InjectiveArrayPropertyValueDescription *)propertyDescription.value;
	GHAssertNotNil(arrayDescription,@"value wasn't set");
	GHAssertTrue(arrayDescription.class == [InjectiveArrayPropertyValueDescription class],@"was not an array class");
	GHAssertTrue(3 == arrayDescription.valueDescriptions.count, @"array dind't have 3 elements had %d",
				 arrayDescription.valueDescriptions.count);
	
	//now get the real value
	NSArray *realArrayValue = [arrayDescription realValueUsingContainer:container];
	GHAssertNotNil(realArrayValue,@"real value wasn't set");
	GHAssertTrue([realArrayValue isKindOfClass:NSArray.class],@"was not an array class");
	GHAssertTrue(3 == realArrayValue.count, @"real array dind't have 3 elements had %d",
				 realArrayValue.count);
	
	
	//test the actual values
	
	NSNumber *integerElement = [realArrayValue objectAtIndex:0];
	GHAssertNotNil(integerElement,@"real value wasn't set for element 0");
	GHAssertTrue([integerElement isKindOfClass:NSNumber.class],@"was not a NSNumber class");
	GHAssertTrue([integerElement isEqualToNumber:INJNINT(1)],@"string not correctly set");
	
	NSString *stringElement = [realArrayValue objectAtIndex:1];
	GHAssertNotNil(stringElement,@"real value wasn't set for element 1");
	GHAssertTrue([stringElement isKindOfClass:NSString.class],@"was not a string class");
	GHAssertTrue([stringElement isEqualToString:@"some text"],@"string not correctly set");
	
	NSString *funkyProvider = [realArrayValue objectAtIndex:2]; //note we get this from mock above
	GHAssertNotNil(funkyProvider,@"class ref wasn't set for element 2");
	GHAssertTrue([funkyProvider isKindOfClass:NSString.class],@"class ref was not looked up correctly");
	GHAssertTrue([funkyProvider isEqualToString:@"CORRECT"],@"class ref not correctly set");
}


- (void)testRealValueNested
{
	//sanity check on the descriptions
	
	NSArray *descriptions = [factory processXMLFile:@"testNestedArrayValue.xml"];
	GHAssertNotNil(descriptions, @"no descriptions were generated");
	InjectiveObjectDescription *description = [descriptions lastObject];
	GHAssertNotNil(description.propertyDescriptions, @"there were no property descriptions");
	GHAssertTrue(1 == description.propertyDescriptions.count, @"didn't create 1 property, created %d", description.propertyDescriptions.count);
	InjectivePropertyDescription *propertyDescription = [description.propertyDescriptions lastObject];
	GHAssertTrue([propertyDescription.type isEqualToString:@"Array"],@"didn't detect correct type");
	GHAssertTrue([propertyDescription.propertyName isEqualToString:@"arrayValue"],@"didn't detect correct property name");
	InjectiveArrayPropertyValueDescription *arrayDescription = (InjectiveArrayPropertyValueDescription *)propertyDescription.value;
	GHAssertNotNil(arrayDescription,@"value wasn't set");
	GHAssertTrue(arrayDescription.class == [InjectiveArrayPropertyValueDescription class],@"was not an array class");
	GHAssertTrue(4 == arrayDescription.valueDescriptions.count, @"array dind't have 4 elements had %d",
				 arrayDescription.valueDescriptions.count);
	
	//now get the real value
	NSArray *realArrayValue = [arrayDescription realValueUsingContainer:container];
	GHAssertNotNil(realArrayValue,@"real value wasn't set");
	GHAssertTrue([realArrayValue isKindOfClass:NSArray.class],@"was not an array class");
	GHAssertTrue(4 == realArrayValue.count, @"real array dind't have 4 elements had %d",
				 realArrayValue.count);
	
	
	//test the actual values
	
	NSNumber *integerElement = [realArrayValue objectAtIndex:0];
	GHAssertNotNil(integerElement,@"real value wasn't set for element 0");
	GHAssertTrue([integerElement isKindOfClass:NSNumber.class],@"was not a NSNumber class");
	GHAssertTrue([integerElement isEqualToNumber:INJNINT(1)],@"string not correctly set");
	
	NSString *stringElement = [realArrayValue objectAtIndex:1];
	GHAssertNotNil(stringElement,@"real value wasn't set for element 1");
	GHAssertTrue([stringElement isKindOfClass:NSString.class],@"was not a string class");
	GHAssertTrue([stringElement isEqualToString:@"some text"],@"Integer not correctly set");
	
	NSString *funkyProvider = [realArrayValue objectAtIndex:2]; //note we get this from mock above
	GHAssertNotNil(funkyProvider,@"class ref wasn't set for element 2");
	GHAssertTrue([funkyProvider isKindOfClass:NSString.class],@"class ref was not looked up correctly");
	GHAssertTrue([funkyProvider isEqualToString:@"CORRECT"],@"class ref not correctly set");
	
	NSArray *nestedArray = [realArrayValue objectAtIndex:3]; //note we get this from mock above
	GHAssertNotNil(nestedArray,@"item didn't translate to an array for element 3");
	GHAssertTrue([nestedArray isKindOfClass:NSArray.class],@"class ref was not looked up correctly");
	GHAssertTrue(nestedArray.count == 3,@"sub array didn't have 3 items");
	
	//now test the nested values
	NSNumber *integerElement2 = [nestedArray objectAtIndex:0];
	GHAssertNotNil(integerElement2,@"real value wasn't set for element 0");
	GHAssertTrue([integerElement2 isKindOfClass:NSNumber.class],@"was not a NSNumber class");
	GHAssertTrue([integerElement2 isEqualToNumber:INJNINT(2)],@"Integer not correctly set");
	
	NSString *stringElement2 = [nestedArray objectAtIndex:1];
	GHAssertNotNil(stringElement2,@"real value wasn't set for element 1");
	GHAssertTrue([stringElement2 isKindOfClass:NSString.class],@"was not a string class");
	GHAssertTrue([stringElement2 isEqualToString:@"some text2"],@"string not correctly set");
	
	NSString *funkyProvider2 = [nestedArray objectAtIndex:2]; //note we get this from mock above
	GHAssertNotNil(funkyProvider2,@"class ref wasn't set for element 2");
	GHAssertTrue([funkyProvider2 isKindOfClass:NSString.class],@"class ref was not looked up correctly");
	GHAssertTrue([funkyProvider2 isEqualToString:@"CORRECT2"],@"class ref not correctly set");
	
	
}

@end
